package net.sunofbeaches.services.impl;

import com.google.gson.Gson;
import com.wf.captcha.ArithmeticCaptcha;
import com.wf.captcha.GifCaptcha;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import net.sunofbeaches.dao.RefreshTokenDao;
import net.sunofbeaches.dao.SettingsDao;
import net.sunofbeaches.dao.UserDao;
import net.sunofbeaches.pojo.RefreshToken;
import net.sunofbeaches.pojo.Setting;
import net.sunofbeaches.pojo.SobUser;
import net.sunofbeaches.response.ResponseResult;
import net.sunofbeaches.response.ResponseState;
import net.sunofbeaches.services.IUserService;
import net.sunofbeaches.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.Map;
import java.util.Random;

@Slf4j
@Service
@Transactional
public class IUserServiceImpl implements IUserService {
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private UserDao userDao;
    @Autowired
    private SettingsDao settingsDao;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @Autowired
    private RefreshTokenDao refreshTokenDao;
    @Autowired
    private Gson gson;

    public HttpServletRequest getRequest(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return requestAttributes.getRequest();
    }

    public HttpServletResponse getResponse(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return requestAttributes.getResponse();
    }


    /**
     * 初始化管理员账号
     *
     * @param sobUser
     * @param request
     * @return
     */
    @Override
    public ResponseResult initManagerAccount(SobUser sobUser, HttpServletRequest request) {
        Setting managerAccountState = settingsDao.findOneByKey(Constants.Settings.MANAGER_ACCOUNT_INIT_STATE);
        if (managerAccountState != null) {
            return ResponseResult.FAILED("管理员账号已经初始化了");
        }
        //检查数据
        if (TextUtils.isEmpty(sobUser.getUserName())) {
            return ResponseResult.FAILED("用户名不能为空");
        }
        if (TextUtils.isEmpty(sobUser.getPassword())) {
            return ResponseResult.FAILED("密码不能为空");
        }
        if (TextUtils.isEmpty(sobUser.getEmail())) {
            return ResponseResult.FAILED("邮箱不能为空");
        }
        //补充数据
        sobUser.setId(String.valueOf(idWorker.nextId()));
        sobUser.setRoles(Constants.User.ROLE_ADMIN);
        sobUser.setAvatar(Constants.User.DEFAULT_AVATAR);
        sobUser.setState(Constants.User.DEFAULT_STATE);
        // 求 ip 地址
        String remoteAddr = request.getRemoteAddr();
        String localAddr = request.getLocalAddr();
        log.info("remoteAddr == > " + remoteAddr);
        log.info("localAddr == > " + localAddr);
        // 对密码加密
        // 原来的密码
        String password = sobUser.getPassword();
        String encode = bCryptPasswordEncoder.encode(password);
        sobUser.setPassword(encode);

        sobUser.setLoginIp(remoteAddr);
        sobUser.setRegIp(remoteAddr);
        sobUser.setCreateTime(new Date());
        sobUser.setUpdateTime(new Date());
        //保存到数据库里
        userDao.save(sobUser);
        //更新已经添加的标记
        //肯定滑的
        Setting setting = new Setting();
        setting.setId(idWorker.nextId() + "");
        setting.setKey(Constants.Settings.MANAGER_ACCOUNT_INIT_STATE);
        setting.setCreateTime(new Date());
        setting.setUpdateTime(new Date());
        setting.setValue("1");
        settingsDao.save(setting);
        return ResponseResult.SUCCESS("初始化成功");
    }

    @Autowired
    private Random random;

    @Qualifier("redisUtil")
    @Autowired
    private RedisUtil redisUtils;

    public static final int[] captcha_font_types = {Captcha.FONT_1,
            Captcha.FONT_2, Captcha.FONT_3, Captcha.FONT_4,
            Captcha.FONT_5, Captcha.FONT_6, Captcha.FONT_7,
            Captcha.FONT_8, Captcha.FONT_9, Captcha.FONT_10};

    /**
     * 发送邮箱验证码
     *
     * @param response
     * @param captchaKey
     * @throws Exception
     */
    @Override
    public void createCaptcha(HttpServletResponse response, String captchaKey) throws Exception {
        if (TextUtils.isEmpty(captchaKey) || captchaKey.length() < 13) {
            return;
        }
        long key = 0;
        try {
            key = Long.parseLong(captchaKey);
        } catch (Exception e) {
            return;
        }
        // 设置请求头为输出图片类型
        response.setContentType("image/gif");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        int captchaType = random.nextInt(3);
        Captcha targetCaptcha = null;
        if (captchaType == 0) {
            // 三个参数分别为宽、高、位数
            targetCaptcha = new SpecCaptcha(200, 60, 5);
        } else if (captchaType == 1) {
            // git 类型
            targetCaptcha = new GifCaptcha(200, 60);
        } else {
            // 算术类型
            targetCaptcha = new ArithmeticCaptcha(200, 60);
            targetCaptcha.setLen(2);
            targetCaptcha.text();
        }

        int index = random.nextInt(captcha_font_types.length);
        log.info("captcha font type index == > " + index);
        targetCaptcha.setFont(captcha_font_types[index]);
        //  数字和字母混合
        targetCaptcha.setCharType(Captcha.TYPE_DEFAULT);
        String content = targetCaptcha.text().toLowerCase();
        log.info("captcha content == >" + content);
        // 保存到 redis
        redisUtils.set(Constants.User.KEY_CAPTCHA_CONTENT + key, content, 60 * 10);
        targetCaptcha.out(response.getOutputStream());
    }

    @Autowired
    private TaskService taskService;

    /**
     * 发送邮箱验证码
     *
     * @param request
     * @param emailAddress
     * @return
     */
    @Override
    public ResponseResult sendEmail(String type, HttpServletRequest request, String emailAddress) {
        if (emailAddress == null) {
            return ResponseResult.FAILED("邮箱地址不可以为空");
        }
        if ("register".equals(type) || "update".equals(type)) {
            SobUser userByEmail = userDao.findOneByEmail(emailAddress);
            if (userByEmail != null) {
                return ResponseResult.FAILED("该邮箱已注册");
            }
        } else if ("forget".equals(type)) {
            SobUser userByEmail = userDao.findOneByEmail(emailAddress);
            if (userByEmail == null) {
                return ResponseResult.FAILED("该邮箱未注册");
            }
        }

        // 1、防止暴力发送，就是不断发地送:同一个邮箱，间隔要超过30秒发一次，同一个Ip，1小时内最多只能发10次《如果是短信，你最多只能发5次)
        String remoteAddr = request.getRemoteAddr();
        log.info("sendEmail == > ip" + remoteAddr);
        if (remoteAddr != null) {
            remoteAddr = remoteAddr.replaceAll(":", "_");
        }
        // 拿出来，如果没有，那就过了
        Integer ipSendTime = (Integer) redisUtils.get(Constants.User.KEY_EMAIL_SEND_IP + remoteAddr);
        if (ipSendTime != null && ipSendTime > 10) {
            return ResponseResult.FAILED("您发送验证码也太频繁了吧!");
        }
        Object hasEmailSend = redisUtils.get(Constants.User.KEY_EMAIL_SEND_ADDRESS + emailAddress);
        if (hasEmailSend != null) {
            return ResponseResult.FAILED("您发送验证码也太频繁了吧!");
        }

        // 2、检查邮箱地址是否正确
        boolean isEmailFormatOk = TextUtils.isEmailAddressOk(emailAddress);
        if (!isEmailFormatOk) {
            return ResponseResult.FAILED("邮箱地址格式不正确");
        }
        // 0~999999
        int code = random.nextInt(999999);
        if (code < 100000) {
            code += 100000;
        }
        log.info("sendEmail == > " + code);
        // 3、发送验证码,6位数:100000~999999
        try {
            // EmailSender.sendRegisterVerifyCode(String.valueOf(code), emailAddress);
            taskService.sendEmailVerifyCode(String.valueOf(code), emailAddress);
        } catch (Exception e) {
            return ResponseResult.FAILED("验证码发送失败,请稍后重试.");
        }
        // 3、做记录
        // 发送记录：code
        if (ipSendTime == null) {
            ipSendTime = 0;
        }
        ipSendTime++;
        // 1个小时有效
        redisUtils.set(Constants.User.KEY_EMAIL_SEND_IP + remoteAddr, ipSendTime, 60 * 60);
        redisUtils.set(Constants.User.KEY_EMAIL_SEND_ADDRESS + emailAddress, "true", 30);
        // 保存code. 10分钟内有效
        redisUtils.set(Constants.User.KEY_EMAIL_CODE_CONTENT + emailAddress, String.valueOf(code), 60 * 10);

        return ResponseResult.SUCCESS("验证码发送成功");
    }

    @Override
    public ResponseResult register(SobUser sobUser, String emailCode, String captchaCode, String captchaKey, HttpServletRequest request) {
        //第一步：检查当前用户名是否已经注册
        String userName = sobUser.getUserName();
        log.info("userName == > " + userName);
        if (TextUtils.isEmpty(userName)) {
            return ResponseResult.FAILED("用户名不可以为空.");
        }
        SobUser userByName = userDao.findOneByUserName(userName);
        if (userByName != null) {
            return ResponseResult.FAILED("该用户名已注册.");
        }
        //第二步：检查邮箱格式是否正确
        String email = sobUser.getEmail();
        log.info("email == > " + email);
        if (TextUtils.isEmpty(email)) {
            return ResponseResult.FAILED("邮箱地址不可以为空.");
        }
        if (!TextUtils.isEmailAddressOk(email)) {
            return ResponseResult.FAILED("邮箱地址格式不正确");
        }
        //第三步：检查该邮箱是否已经注册
        SobUser userByEmail = userDao.findOneByEmail(email);
        if (userByEmail != null) {
            return ResponseResult.FAILED("该邮箱地址已经注册");
        }
        //第四步：检查邮箱验证码是否正确
        String emailVerifyCode = (String) redisUtils.get(Constants.User.KEY_EMAIL_CODE_CONTENT + email);
        if (TextUtils.isEmpty(emailVerifyCode)) {
            return ResponseResult.FAILED("邮箱验证码已过期");
        }
        if (!emailVerifyCode.equals(emailCode)) {
            return ResponseResult.FAILED("邮箱验证码不正确");
        } else {
            //正确，干掉redis里的内容
            redisUtils.del(Constants.User.KEY_EMAIL_CODE_CONTENT + email);
        }
        //第五步：检查图灵验证码是否正确
        String captchaVerifyCode = (String) redisUtils.get(Constants.User.KEY_CAPTCHA_CONTENT + captchaKey);
        if (TextUtils.isEmpty(captchaVerifyCode)) {
            return ResponseResult.FAILED("人类验证码已过期");
        }
        if (!captchaVerifyCode.equals(captchaCode)) {
            return ResponseResult.FAILED("人类验证码不正确");
        } else {
            redisUtils.del(Constants.User.KEY_CAPTCHA_CONTENT + captchaKey);
        }
        //达到可以注册的条件
        //第六步：对密码进行加密
        String password = sobUser.getPassword();
        if (TextUtils.isEmpty(password)) {
            return ResponseResult.FAILED("密码不可以为空");
        }
        sobUser.setPassword(bCryptPasswordEncoder.encode(sobUser.getPassword()));
        //第七步：补全数据
        //包括：注册IP,登录IP,角色,头像,创建时间,更新时间
        String ipAddress = request.getRemoteAddr();
        sobUser.setRegIp(ipAddress);
        sobUser.setLoginIp(ipAddress);
        sobUser.setUpdateTime(new Date());
        sobUser.setCreateTime(new Date());
        sobUser.setAvatar(Constants.User.DEFAULT_AVATAR);
        sobUser.setRoles(Constants.User.ROLE_NORMAL);
        sobUser.setState("1");
        sobUser.setId(idWorker.nextId() + "");
        //第八步：保存到数据库中
        userDao.save(sobUser);
        //第九步：返回结果
        return ResponseResult.GET(ResponseState.JOIN_IN_SUCCESS);
    }

    @Override
    public ResponseResult doLogin(String captcha,
                                  String captchaKey,
                                  SobUser sobUser,
                                  HttpServletRequest request,
                                  HttpServletResponse response) {
        String captchaValue = (String) redisUtils.get(Constants.User.KEY_CAPTCHA_CONTENT + captchaKey);
        if (!captcha.equals(captchaValue)) {
            return ResponseResult.FAILED("人类验证码不正确");
        }
        // 验证成功 删除redis里的验证码
        redisUtils.del(Constants.User.KEY_CAPTCHA_CONTENT + captchaKey);
        // 有可能是邮箱，也有可能是用户名
        String userName = sobUser.getUserName();
        log.info("username");
        if (TextUtils.isEmpty(userName)) {
            return ResponseResult.FAILED("账号不可以为空");
        }
        String password = sobUser.getPassword();
        if (TextUtils.isEmpty(password)) {
            return ResponseResult.FAILED("密码不可以为空.");
        }
        SobUser userFromDb = userDao.findOneByUserName(userName);
        if (userFromDb == null) {
            userFromDb = userDao.findOneByEmail(userName);
        }
        if (userFromDb == null) {
            return ResponseResult.FAILED("用户名或密码不正确");
        }
        //用户存在
        //对比密码
        /**
         * setMaxAge(int expiry) expiry 参数为 -1 时表示永久
         */
        boolean matches = bCryptPasswordEncoder.matches(password, userFromDb.getPassword());
        if (!matches) {
            return ResponseResult.FAILED("用户名或密码不正确");
        }
        //密码是正确
        //判断用户状态，如果是非正常的状态，则返回结果
        if (!"1".equals(userFromDb.getState())) {
            return ResponseResult.FAILED("当前账号已被禁止.");
        }
        createToken(response, userFromDb);

        // Cookie cookie = new Cookie(Constants.User.COOKIE_TOKE_KEY, tokenKey);
        // 这个要动态获取，可以从request里获取，
        // TODO:后面提供一个工具类给大家使用
        // 写入给到前端
        // cookie.setComment("localhost");
        // cookie.setMaxAge(60 * 60 * 24 * 356);// 参数为 -1 时表示永久
        // cookie.setPath("/");
        // response.addCookie(cookie);
        return ResponseResult.SUCCESS("登录成功");
    }

    private String createToken(HttpServletResponse response, SobUser userFromDb) {
        refreshTokenDao.deleteAllByUserId(userFromDb.getId());
        // 生成token
        Map<String, Object> claims = ClaimsUtils.sobUser2Claims(userFromDb);
        // token默认有效为2个小时
        String token = JwtUtil.createToken(claims);
        // 返回token的md5值，token 会保存到redis里
        // 前端访问的时候，携带token的md5key,从redis 中获取即可
        String tokenKey = DigestUtils.md5DigestAsHex(token.getBytes());
        // 保存token到redis里，有效期为2个小时，key 是tokenKey
        redisUtils.set(Constants.User.KET_TOKEN + tokenKey, token, 60 * 60 * 2);
        // 把tokenKey写到cookies里
        CookieUtils.setUpCookie(response, Constants.User.COOKIE_TOKE_KEY, tokenKey);
        // 生成 refreshTokenValue
        String refreshTokenValue = JwtUtil.createRefreshToken(userFromDb.getId(), Constants.TimeValueInMillions.MONTH);

        RefreshToken refreshToken = new RefreshToken();
        refreshToken.setId(idWorker.nextId() + "");
        refreshToken.setRefreshToken(refreshTokenValue);
        refreshToken.setUserId(userFromDb.getId());
        refreshToken.setTokenKey(tokenKey);
        refreshToken.setCreateTime(new Date());
        refreshToken.setUpdateTime(new Date());
        refreshTokenDao.save(refreshToken);
        return tokenKey;
    }

    /**
     * 本质，通过携带的token_key检查用户是否有登录，如果登录了，就返回用户信息
     *
     * @return
     */
    @Override
    public SobUser checkSobUser() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        HttpServletResponse response = requestAttributes.getResponse();
        // 拿到token_key
        String tokenKey = CookieUtils.getCookie(request, Constants.User.COOKIE_TOKE_KEY);
        log.info("checkSobUser tokenKey => " + tokenKey);
        SobUser sobUser = paresByTokenKey(tokenKey);
        log.info("checkSobUser tokenKey => " + sobUser);
        if (sobUser == null) {
            // 说明解析出错了,过期了
            // 1、去mysql查询refreshToken
            RefreshToken refreshToken = refreshTokenDao.findOneByTokenKey(tokenKey);
            // 2、如果不存在，就是当前访问没有登录，提示用户登录
            if (refreshToken == null) {
                log.info("refresh token is null");
                return null;
            }
            // 3、如果存在，就解析refreshToken
            try {
                JwtUtil.parseJWT(refreshToken.getRefreshToken());
                // 5、如果refreshToken有效，创建新的token，和新的refreshToken
                String userId = refreshToken.getUserId();
                SobUser userFromDb = userDao.findOneById(userId);
                // 千万别这么干，事务还没有提交，如果这样设置，数据库里的密码就没有了
                // userFromDb.setPassword("");
                // 删除 refreshToken 的记录
                refreshTokenDao.deleteById(refreshToken.getId());
                String newTokenKey = createToken(response, userFromDb);
                // 返回token
                log.info("created new token and refresh token...");
                log.info("newTokenKey ==> " + newTokenKey);
                return paresByTokenKey(newTokenKey);
            } catch (Exception ex) {
                log.info("refresh token is 过期了...");
                // 4、如果refreshToken过期了，就当前访问没有登录，提示用户登录
                return null;
            }
        }
        return sobUser;
    }

    private SobUser paresByTokenKey(String tokeKey) {
        String token = (String) redisUtils.get(Constants.User.KET_TOKEN + tokeKey);
        log.info("paresByTokenKey token ==> " + token);
        if (token != null) {
            try {
                log.info("token not's null");
                Claims claims = JwtUtil.parseJWT(token);
                return ClaimsUtils.claims2Claims(claims);
            } catch (Exception e) {
                log.info("paresByTokenKey Exception");
                return null;
            }
        }
        log.info("paresByTokenKey null");
        return null;
    }

    @Override
    public ResponseResult getUserInfo(String userId) {
        //从数据里获取
        SobUser user = userDao.findOneById(userId);
        //判断结果
        if (user == null) {
            return ResponseResult.FAILED("用户不存在");
        }
        //如果存在，就复制对象，清空密码、Email、登录ID，注册IP
        String userJson = gson.toJson(user);
        SobUser newSobUser = gson.fromJson(userJson, SobUser.class);
        newSobUser.setPassword("");
        newSobUser.setEmail("");
        newSobUser.setRoles("");
        newSobUser.setLoginIp("");

        return ResponseResult.SUCCESS("获取成功.").setData(user);
    }

    @Override
    public ResponseResult checkEmail(String email) {
        SobUser user = userDao.findOneByEmail(email);
        return user == null ? ResponseResult.FAILED("该邮箱未注册.") : ResponseResult.SUCCESS("该邮箱已经注册");
    }

    @Override
    public ResponseResult checkUserName(String userName) {
        SobUser user = userDao.findOneByUserName(userName);
        return user == null ? ResponseResult.FAILED("该用户名未注册.") : ResponseResult.SUCCESS("该用户名已经注册");
    }

    /**
     * 更改用户信息
     *
     * @param userId
     * @param sobUser
     * @return
     */
    @Override
    public ResponseResult updateUserInfo(String userId, SobUser sobUser) {
        SobUser userFromTokenKey = checkSobUser();
        log.info("userFromTokenKey getUserName ==> " + userFromTokenKey.getUserName());
        log.info("userFromTokenKey getId ==> " + userFromTokenKey.getId());
        if (userFromTokenKey == null) {
            return ResponseResult.ACCOUNT_NOT_LOGIN();
        }
        SobUser userFromDb = userDao.findOneById(userFromTokenKey.getId());

        // 判断用户的ID是否一致,如果一致才可以修改
        if (!userFromDb.getId().equals(userId)) {
            return ResponseResult.GET_RESOURCE_FAILED();
        }
        // 可以进行修改
        // 可经修改的项
        //用户名
        String userName = sobUser.getUserName();
        if (!TextUtils.isEmpty(userName)) {
            SobUser userByUserName = userDao.findOneByUserName(userName);
            if (userByUserName != null) {
                return ResponseResult.FAILED("该用户已注册");
            }
            userFromDb.setUserName(userName);
        }
        // 头像
        if (!TextUtils.isEmpty(sobUser.getAvatar())) {
            userFromDb.setAvatar(sobUser.getAvatar());
        }
        //签名,可以为空
        userFromDb.setSign(sobUser.getSign());
        userDao.save(userFromDb);
        String tokenKey = CookieUtils.getCookie(getRequest(), Constants.User.COOKIE_TOKE_KEY);
        log.info("tokenKey ==> " + tokenKey);
        redisUtils.del(Constants.User.KET_TOKEN + tokenKey);
        return ResponseResult.SUCCESS("用户信息更新成功.");
    }

    /**
     * 删除用户
     *
     * @param userId
     * @return
     */
    @Override
    public ResponseResult deleteUserById(String userId) {
        SobUser currentUser = checkSobUser();
        if (currentUser == null) {
            return ResponseResult.ACCOUNT_NOT_LOGIN();
        }
        // 判断角色
        if (!Constants.User.ROLE_ADMIN.equals(currentUser.getRoles())) {
            return ResponseResult.PERMISSION_DENIED();
        }
        // 可以删除用户
        int result = userDao.deleteUserByState(userId);
        if (result > 0) {
            return ResponseResult.SUCCESS("删除成功");
        }
        return ResponseResult.FAILED("用户不存在");
    }

    /**
     * 查看用户列表
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public ResponseResult listUsers(int page, int size) {
//        SobUser currentUser = checkSobUser(request, response);
//        if (currentUser == null) {
//            return ResponseResult.ACCOUNT_NOT_LOGIN();
//        }
//        // 判断角色
//        if (!Constants.User.ROLE_ADMIN.equals(currentUser.getRoles())) {
//            return ResponseResult.PERMISSION_DENIED();
//        }
        if (page < Constants.Page.DEFAULT_PAGE) {
            page = Constants.Page.DEFAULT_PAGE;
        }
        if (size < Constants.Page.DEFAULT_SIZE) {
            size = Constants.Page.DEFAULT_SIZE;
        }
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        Pageable pageable = PageRequest.of(page - 1, size, sort);
        Page<SobUser> all = userDao.listAllUserNoPassword(pageable);
        return ResponseResult.SUCCESS("获取用户列表成功.").setData(all);
    }

    /**
     * 更新密码
     *
     * @param verifyCode
     * @param sobUser
     * @return
     */
    @Override
    public ResponseResult updateUserPassword(String verifyCode, SobUser sobUser) {
        //检查邮箱是否有填写
        String email = sobUser.getEmail();
        if (TextUtils.isEmpty(email)) {
            return ResponseResult.FAILED("邮箱不可以未空");
        }
        //根据邮箱去redis里拿验证
        //进行对比
        String redisVerifyCode = (String) redisUtils.get(Constants.User.KEY_EMAIL_CODE_CONTENT + email);
        if (redisVerifyCode == null || !redisVerifyCode.equals(verifyCode)) {
            return ResponseResult.FAILED("验证码错误");
        }
        redisUtils.del(Constants.User.KEY_EMAIL_CODE_CONTENT + email);
        int result = userDao.updatePasswordByEmail(bCryptPasswordEncoder.encode(sobUser.getPassword()), email);
        //修改密码
        return result > 0 ? ResponseResult.SUCCESS("密码修改成功") : ResponseResult.FAILED("密码修改失败");
    }

    @Override
    public ResponseResult updateEmail(String email, String verifyCode) {
        SobUser sobUser = this.checkSobUser();
        if (sobUser == null) {
            return ResponseResult.ACCOUNT_NOT_LOGIN();
        }
        String redisVerifyCode = (String) redisUtils.get(Constants.User.KEY_EMAIL_CODE_CONTENT + email);
        if (TextUtils.isEmpty(redisVerifyCode) || !redisVerifyCode.equals(verifyCode)) {
            return ResponseResult.FAILED("验证码错误");
        }
        // 验证码正确，删除验证码
        redisUtils.del(Constants.User.KEY_EMAIL_CODE_CONTENT + email);
        int result = userDao.updateEmailById(email, sobUser.getId());
        return result > 0 ? ResponseResult.SUCCESS("邮箱修改成功") : ResponseResult.FAILED("邮箱修改失败");
    }

    @Override
    public ResponseResult doLogout() {
        // 拿到token_key
        String tokenKey = CookieUtils.getCookie(getRequest(), Constants.User.COOKIE_TOKE_KEY);
        if (TextUtils.isEmpty(tokenKey)) {
            return ResponseResult.ACCOUNT_NOT_LOGIN();
        }
        // 刪除redis里的token
        redisUtils.del(Constants.User.KET_TOKEN+tokenKey);
        // 删除mysql里的refreshToken
        refreshTokenDao.deleteAllByUserId(tokenKey);
        // 删除cookie里的token_key
        CookieUtils.deleteCookie(getResponse(),Constants.User.COOKIE_TOKE_KEY);
        return ResponseResult.SUCCESS("退出登录成功");
    }
}